#include "scheduler.hpp"

#include <iostream>

class ChronoTimer {
 public:
  ChronoTimer() = default;
  void start() { startTime = std::chrono::high_resolution_clock::now(); }
  void finish(std::string&& msg) {
    auto finish = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsed = finish - startTime;
    std::cout << msg << " : " << elapsed.count() * 1000 << " ms\n";  // NOLINT
  }

 private:
  std::chrono::high_resolution_clock::time_point startTime;
};

float benchFunc(uint64_t loopLen) {
  float acc = 0;
  for (uint64_t k = 0; k < loopLen; ++k) acc += k;  // NOLINT
  return acc;
}

void bench(uint32_t iter) {
  OldScheduler scheduler;
  std::cout << "Benchmark with " << iter << " iterations\n";

  const uint64_t num_blocks = 1000;
  const uint64_t loopLen = 100;
  ChronoTimer timer;

  timer.start();
  for (uint64_t it = 0; it < iter; ++it) {
    std::vector<std::future<int>> results;
    for (uint64_t i = 0; i < num_blocks; i++) {  // NOLINT
      results.emplace_back(scheduler.submit_task(
          i % scheduler.cpu_worker_num(), [loopLen]() {
            benchFunc(loopLen);
            return 0;
          }));
    }

    for (auto& result : results) {  // NOLINT
      result.get();
    }
  }
  timer.finish("scheduler: time in ms: ");
}

int main() {
  for (uint32_t i = 0; i < 5; ++i) bench(100);  // NOLINT ~600ms
  for (uint32_t i = 0; i < 5; ++i) bench(50);   // NOLINT
  for (uint32_t i = 0; i < 5; ++i) bench(20);   // NOLINT
  for (uint32_t i = 0; i < 5; ++i) bench(10);   // NOLINT
  for (uint32_t i = 0; i < 5; ++i) bench(5);    // NOLINT
}
